home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / iface.c < prev    next >
Text File  |  1993-07-30  |  14KB  |  596 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI
  5.  */
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "proc.h"
  11. #include "iface.h"
  12. #include "ip.h"
  13. #include "netuser.h"
  14. #include "ax25.h"
  15. #include "enet.h"
  16. #include "pktdrvr.h"
  17. #include "cmdparse.h"
  18. #include "commands.h"
  19. #if defined(PM)
  20. #include "trace.h"
  21. #endif
  22. #define NULLFP1 (int(*) __ARGS((struct iface *,char *,char *,int16,struct mbuf *)))0
  23.  
  24. #ifdef NETROM
  25. extern int Nr_numiface;
  26. extern struct iface *Nr_iface;
  27. #endif
  28.  
  29. static void showiface __ARGS((struct iface *ifp));
  30. static int mask2width __ARGS((int32 mask));
  31. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  32. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  33. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  34. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  35. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  36. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  37. static int ifforw __ARGS((int argc,char *argv[],void *p));
  38. static int ifencap __ARGS((int argc,char *argv[],void *p));
  39. static int ifdescr __ARGS((int argc,char *argv[],void *p));
  40.  
  41. /* Interface list header */
  42. struct iface *Ifaces = &Loopback;
  43.  
  44. /* Encapsulation pseudo-interface */
  45.  
  46. #if defined(ENCAP)
  47. struct iface Encap = {
  48.     NULLIF,
  49.     "encap",    /* name        */
  50.     NULLCHAR,
  51.     INADDR_ANY,    /* addr        0.0.0.0 */
  52.     0xffffffffL,    /* broadcast    255.255.255.255 */
  53.     0xffffffffL,    /* netmask    255.255.255.255 */
  54.     MAXINT16,    /* mtu        No limit */
  55.     0,        /* flags    */
  56.     0,        /* trace    */
  57.     NULLCHAR,    /* trfile    */
  58.     NULLFILE,    /* trfp        */
  59. #if defined(PM)
  60.     NULLSESSION,        /* session hwnd    */
  61.     NULLCHAR,
  62.     0,
  63. #endif
  64.     NULLIF,        /* forw        */
  65.     NULLPROC,    /* rxproc    */
  66.     NULLPROC,    /* txproc    */
  67.     NULLPROC,    /* supv        */
  68.     0,        /* dev        */
  69.     NULL,        /* (*ioctl)    */
  70.     NULLFP,        /* (*iostatus)    */
  71.     NULLFP,        /* (*stop)    */
  72.     NULLCHAR,    /* hwaddr    */
  73.     NULL,        /* extension    */
  74.     CL_NONE,    /* type        */
  75.     0,        /* xdev        */
  76.     0,        /* port        */
  77.     &Iftypes[0],    /* iftype    */
  78.     ip_encap,    /* (*send)    */
  79.     NULLFP1,        /* (*output)    */
  80.     NULLFP,        /* (*raw)    */
  81.     NULLVFP,    /* (*show)    */
  82.     NULLFP,        /* (*discard)    */
  83.     NULLFP,        /* (*echo)    */
  84.     0,        /* ipsndcnt    */
  85.     0,        /* rawsndcnt    */
  86.     0,        /* iprecvcnt    */
  87.     0,        /* rawrcvcnt    */
  88.     0,        /* lastsent    */
  89.     0,        /* lastrecv    */
  90. };
  91. #endif
  92.  
  93. /* Loopback pseudo-interface */
  94. struct iface Loopback = {
  95. #if defined(ENCAP)
  96.     (struct iface *)&Encap,        /* Link to next entry */
  97. #else
  98.     (struct iface *)NULLIF,        /* Link to next entry */
  99. #endif
  100.     "loopback",    /* name        */
  101.     NULLCHAR,
  102.     0x7f000001L,    /* addr        127.0.0.1 */
  103.     0xffffffffL,    /* broadcast    255.255.255.255 */
  104.     0xffffffffL,    /* netmask    255.255.255.255 */
  105.     MAXINT16,    /* mtu        No limit */
  106.     0,        /* flags    */
  107.     0,        /* trace    */
  108.     NULLCHAR,    /* trfile    */
  109.     NULLFILE,    /* trfp        */
  110. #if defined(PM)
  111.     NULLSESSION,        /* session hwnd */
  112.     NULLCHAR,
  113.     0,
  114. #endif
  115.     NULLIF,        /* forw        */
  116.     NULLPROC,    /* rxproc    */
  117.     NULLPROC,    /* txproc    */
  118.     NULLPROC,    /* supv        */
  119.     0,        /* dev        */
  120.     NULL,        /* (*ioctl)    */
  121.     NULLFP,        /* (*iostatus)    */
  122.     NULLFP,        /* (*stop)    */
  123.     NULLCHAR,    /* hwaddr    */
  124.     NULL,        /* extension    */
  125.     CL_NONE,    /* type        */
  126.     0,        /* xdev        */
  127.     0,        /* port        */
  128.     &Iftypes[0],    /* iftype    */
  129.     NULLFP,        /* (*send)    */
  130.     NULLFP1,        /* (*output)    */
  131.     NULLFP,        /* (*raw)    */
  132.     NULLVFP,    /* (*show)    */
  133.     NULLFP,        /* (*discard)    */
  134.     NULLFP,        /* (*echo)    */
  135.     0,        /* ipsndcnt    */
  136.     0,        /* rawsndcnt    */
  137.     0,        /* iprecvcnt    */
  138.     0,        /* rawrcvcnt    */
  139.     0,        /* lastsent    */
  140.     0,        /* lastrecv    */
  141. };
  142.  
  143. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  144.  
  145. struct cmds Ifcmds[] = {
  146.     "broadcast",        ifbroad,    0,    2,    NULLCHAR,
  147.     "description",      ifdescr,    0,  0,  NULLCHAR,
  148.     "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  149.     "forward",        ifforw,        0,    2,    NULLCHAR,
  150.     "ipaddress",        ifipaddr,    0,    2,    NULLCHAR,
  151.     "linkaddress",        iflinkadr,    0,    2,    NULLCHAR,
  152.     "mtu",            ifmtu,        0,    2,    NULLCHAR,
  153.     "netmask",        ifnetmsk,    0,    2,    NULLCHAR,
  154.     "rxbuf",        ifrxbuf,    0,    2,    NULLCHAR,
  155.     NULLCHAR,
  156. };
  157.  
  158. /* Set interface parameters */
  159. int
  160. doifconfig(argc,argv,p)
  161. int argc;
  162. char *argv[];
  163. void *p;
  164. {
  165.     struct iface *ifp;
  166.     int i;
  167.  
  168.     if(argc < 2){
  169.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  170.             showiface(ifp);
  171.         return 0;
  172.     }
  173.     if((ifp = if_lookup(argv[1])) == NULLIF){
  174.         tprintf(Badinterface,argv[1]);
  175.         return 1;
  176.     }
  177.     if(argc == 2){
  178.         showiface(ifp);
  179.         if ( ifp->show != NULLVFP ) {
  180.             (*ifp->show)(ifp);
  181.         }
  182.         return 0;
  183.     }
  184.     if(argc == 3){
  185.         tprintf("Argument missing\n");
  186.         return 1;
  187.     }
  188.     for(i=2;i<argc-1;i+=2)
  189.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  190.  
  191.     return 0;
  192. }
  193.  
  194. /* Set interface IP address */
  195. static int
  196. ifipaddr(argc,argv,p)
  197. int argc;
  198. char *argv[];
  199. void *p;
  200. {
  201.     struct iface *ifp = p;
  202.  
  203.     ifp->addr = resolve(argv[1]);
  204.     return 0;
  205. }
  206.  
  207.  
  208. /* Set link (hardware) address */
  209. static int
  210. iflinkadr(argc,argv,p)
  211. int argc;
  212. char *argv[];
  213. void *p;
  214. {
  215.     struct iface *ifp = p;
  216.  
  217.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  218.         tprintf("Can't set link address\n");
  219.         return 1;
  220.     }
  221.     if(ifp->hwaddr != NULLCHAR)
  222.         free(ifp->hwaddr);
  223.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  224.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  225. #ifdef MAILBOX
  226. #ifdef NETROM
  227.     if(ifp == Nr_iface) /*the netrom call just got changed! - WG7J*/
  228.         setmbnrid();
  229. #endif
  230. #endif
  231.     return 0;
  232. }
  233.  
  234. /* Set interface broadcast address. This is actually done
  235.  * by installing a private entry in the routing table.
  236.  */
  237. static int
  238. ifbroad(argc,argv,p)
  239. int argc;
  240. char *argv[];
  241. void *p;
  242. {
  243.     struct iface *ifp = p;
  244.     struct route *rp;
  245.  
  246.     rp = rt_blookup(ifp->broadcast,32);
  247.     if(rp != NULLROUTE && rp->iface == ifp)
  248.         rt_drop(ifp->broadcast,32);
  249.     ifp->broadcast = resolve(argv[1]);
  250.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  251.     return 0;
  252. }
  253.  
  254. /* Set the network mask. This is actually done by installing
  255.  * a routing entry.
  256.  */
  257. static int
  258. ifnetmsk(argc,argv,p)
  259. int argc;
  260. char *argv[];
  261. void *p;
  262. {
  263.     struct iface *ifp = p;
  264.     struct route *rp;
  265.  
  266.     /* Remove old entry if it exists */
  267.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  268.     if(rp != NULLROUTE)
  269.         rt_drop(rp->target,rp->bits);
  270.  
  271.     ifp->netmask = htol(argv[1]);
  272.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  273.     return 0;
  274. }
  275.  
  276. /* Command to set interface encapsulation mode */
  277. static int
  278. ifencap(argc,argv,p)
  279. int argc;
  280. char *argv[];
  281. void *p;
  282. {
  283.     struct iface *ifp = p;
  284.  
  285.     if(setencap(ifp,argv[1]) != 0){
  286.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  287.         return 1;
  288.     }
  289.     return 0;
  290. }
  291. /* Function to set encapsulation mode */
  292. int
  293. setencap(ifp,mode)
  294. struct iface *ifp;
  295. char *mode;
  296. {
  297.     struct iftype *ift;
  298.  
  299.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  300.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  301.             break;
  302.     if(ift->name == NULLCHAR){
  303.         return -1;
  304.     }
  305.     ifp->iftype = ift;
  306.     ifp->send = ift->send;
  307.     ifp->output = ift->output;
  308.     ifp->type = ift->type;
  309.     return 0;
  310. }
  311. /* Set interface receive buffer size */
  312. static int
  313. ifrxbuf(argc,argv,p)
  314. int argc;
  315. char *argv[];
  316. void *p;
  317. {
  318.     return 0;    /* To be written */
  319. }
  320.  
  321. /* Set interface Maximum Transmission Unit */
  322. static int
  323. ifmtu(argc,argv,p)
  324. int argc;
  325. char *argv[];
  326. void *p;
  327. {
  328.     struct iface *ifp = p;
  329.  
  330.     ifp->mtu = atoi(argv[1]);
  331.     return 0;
  332. }
  333.  
  334. /* Set interface forwarding */
  335. static int
  336. ifforw(argc,argv,p)
  337. int argc;
  338. char *argv[];
  339. void *p;
  340. {
  341.     struct iface *ifp = p;
  342.  
  343.     ifp->forw = if_lookup(argv[1]);
  344.     if(ifp->forw == ifp)
  345.         ifp->forw = NULLIF;
  346.     return 0;
  347. }
  348.  
  349. /*give a little description for each interface - WG7J*/
  350. static int
  351. ifdescr(argc,argv,p)
  352. int argc;
  353. char *argv[];
  354. void *p;
  355. {
  356.     struct iface *ifp = p;
  357.  
  358. #ifdef NETROM
  359. #ifdef ENCAP
  360.     if((ifp == &Loopback) || (ifp == &Encap) || (ifp == Nr_iface))
  361. #else
  362.     if((ifp == &Loopback) || (ifp == Nr_iface))
  363. #endif /*ENCAP*/
  364. #else  /*NETROM*/
  365. #ifdef ENCAP
  366.     if((ifp == &Loopback) || (ifp == &Encap))
  367. #else
  368.     if(ifp == &Loopback)
  369. #endif /*ENCAP*/
  370. #endif /*NETROM*/
  371.         return 0;
  372.  
  373.     if(ifp->descr != NULLCHAR){
  374.         free(ifp->descr);
  375.         ifp->descr = NULLCHAR;        /* reset the pointer */
  376.     }
  377.     if(!strlen(argv[1]))
  378.         return 0;           /* clearing the buffer */
  379.  
  380.     ifp->descr = mallocw(strlen(argv[1])+5); /* allow for the EOL char etc */
  381.     strcpy(ifp->descr, argv[1]);
  382.     strcat(ifp->descr, "\n");         /* add the EOL char */
  383.  
  384.     return 0;
  385. }
  386.  
  387.  
  388.  
  389. /* Display the parameters for a specified interface */
  390. static void
  391. showiface(ifp)
  392. register struct iface *ifp;
  393. {
  394.     char tmp[25];
  395.  
  396.     tprintf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  397.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  398.     if(ifp->iftype == NULLIFT){
  399.         tprintf("not set\n");
  400.     } else {
  401.         tprintf("%s\n",ifp->iftype->name);
  402.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  403.             tprintf("           Link addr %s\n",
  404.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  405.     }
  406.     tprintf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  407.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  408.     if(ifp->forw != NULLIF)
  409.         tprintf("           output forward to %s\n",ifp->forw->name);
  410.     tprintf("           sent: ip %lu tot %lu idle %s\n",
  411.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  412.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  413.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  414.     if(ifp->descr != NULLCHAR)
  415.         tprintf("           descr: %s",ifp->descr);
  416.  
  417. }
  418.  
  419. /* Command to detach an interface */
  420. int
  421. dodetach(argc,argv,p)
  422. int argc;
  423. char *argv[];
  424. void *p;
  425. {
  426.     register struct iface *ifp;
  427.  
  428.     if((ifp = if_lookup(argv[1])) == NULLIF){
  429.         tprintf(Badinterface,argv[1]);
  430.         return 1;
  431.     }
  432.     if(if_detach(ifp) == -1)
  433.         tprintf("Can't detach loopback or encap interface\n");
  434.     return 0;
  435. }
  436. /* Detach a specified interface */
  437. int
  438. if_detach(ifp)
  439. register struct iface *ifp;
  440. {
  441.     struct iface *iftmp;
  442.     struct route *rp,*rptmp;
  443.     int i,j;
  444.  
  445. #ifdef ENCAP
  446.     if(ifp == &Loopback || ifp == &Encap)
  447. #else
  448.     if(ifp == &Loopback)
  449. #endif
  450.             return -1;
  451.  
  452.     /* Drop all routes that point to this interface */
  453.     if(R_default.iface == ifp)
  454.         rt_drop(0L,0);    /* Drop default route */
  455.  
  456.     for(i=0;i<HASHMOD;i++){
  457.         for(j=0;j<32;j++){
  458.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  459.                 /* Save next pointer in case we delete this entry */
  460.                 rptmp = rp->next;
  461.                 if(rp->iface == ifp)
  462.                     rt_drop(rp->target,rp->bits);
  463.             }
  464.         }
  465.     }
  466.     /* Unforward any other interfaces forwarding to this one */
  467.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  468.         if(iftmp->forw == ifp)
  469.             iftmp->forw = NULLIF;
  470.     }
  471. #if defined(PM)
  472. /*    terminate any trace in progress */
  473.     if (ifp->sp)
  474.         {
  475.         freeTrace(ifp->sp);
  476.         free(ifp->sp->name);
  477.         free(ifp->pszTraceBuffer);
  478.         ifp->pszTraceBuffer = (char *)NULL;
  479.         free(ifp->sp);
  480.         ifp->sp = NULLSESSION;
  481.         ifp->trfp = NULL;
  482.         }
  483. #endif
  484.     /* Call device shutdown routine, if any */
  485.     if(ifp->stop != NULLFP)
  486.         (*ifp->stop)(ifp);
  487.  
  488.     killproc(ifp->rxproc);
  489.     killproc(ifp->txproc);
  490.     killproc(ifp->supv);
  491.  
  492. #ifdef NETROM
  493.     /*make sure that the netrom interface is properly detached
  494.      *fixed 11/15/91, Johan. K. Reinalda, WG7J/PA3DIS
  495.      */
  496.     if(strcmp(ifp->name,"netrom") == 0) {
  497.             Nr_numiface = 0; /*this 'resets' all active netrom interfaces*/
  498.             Nr_iface = NULLIF;
  499.     }
  500. #endif
  501.  
  502.     /* Free allocated memory associated with this interface */
  503.     if(ifp->name != NULLCHAR)
  504.         free(ifp->name);
  505.     if(ifp->hwaddr != NULLCHAR)
  506.         free(ifp->hwaddr);
  507.  
  508.     /* Remove from interface list */
  509.     if(ifp == Ifaces){
  510.         Ifaces = ifp->next;
  511.     } else {
  512.         /* Search for entry just before this one
  513.          * (necessary because list is only singly-linked.)
  514.          */
  515.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  516.             if(iftmp->next == ifp)
  517.                 break;
  518.         if(iftmp != NULLIF && iftmp->next == ifp)
  519.             iftmp->next = ifp->next;
  520.     }
  521.     /* Finally free the structure itself */
  522.     free((char *)ifp);
  523.     return 0;
  524. }
  525.  
  526. /* Given the ascii name of an interface, return a pointer to the structure,
  527.  * or NULLIF if it doesn't exist
  528.  */
  529. struct iface *
  530. if_lookup(name)
  531. char *name;
  532. {
  533.     register struct iface *ifp;
  534.  
  535.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  536.         if(strcmp(ifp->name,name) == 0)
  537.             break;
  538.     return ifp;
  539. }
  540.  
  541. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  542.  * NULLIF otherwise.
  543.  * This is used to tell if an incoming IP datagram is for us, or if it
  544.  * has to be routed.
  545.  */
  546. struct iface *
  547. ismyaddr(addr)
  548. int32 addr;
  549. {
  550.     register struct iface *ifp;
  551.  
  552.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  553.         if(addr == ifp->addr)
  554.             break;
  555.     return ifp;
  556. }
  557.  
  558. /* Given a network mask, return the number of contiguous 1-bits starting
  559.  * from the most significant bit.
  560.  */
  561. static int
  562. mask2width(mask)
  563. int32 mask;
  564. {
  565.     int width,i;
  566.  
  567.     width = 0;
  568.     for(i = 31;i >= 0;i--){
  569.         if(!(mask & (1L << i)))
  570.             break;
  571.         width++;
  572.     }
  573.     return width;
  574. }
  575.  
  576. /* return buffer with name + comment */
  577. char *
  578. if_name(ifp,comment)
  579. struct iface *ifp;
  580. char *comment;
  581. {
  582.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  583.     strcpy( result, ifp->name );
  584.     return strcat( result, comment );
  585. }
  586.  
  587. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  588. int
  589. bitbucket(ifp,bp)
  590. struct iface *ifp;
  591. struct mbuf *bp;
  592. {
  593.     free_p(bp);
  594.     return 0;
  595. }
  596.